package com.xishu.service;

import com.xishu.config.Config;
import com.xishu.config.Constant;
import com.xishu.dao.jpa.PayTypeDao;
import com.xishu.entity.order.Order;
import com.xishu.entity.shop.PayType;
import com.xishu.entity.shop.PayTypeName;
import com.xishu.entity.shop.Shop;
import com.xishu.exception.ResponseStatusException;
import com.xishu.response.ResponseStatus;
import com.xishu.response.VerifyUtil;
import com.xishu.util.BeanUtil;
import com.xishu.util.JRedisUtil;
import com.xishu.util.Tools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.xishu.config.Constant.*;

public class PayTypeService implements Tools {
    private static Logger logger = LoggerFactory.getLogger(PayTypeService.class);
    private static PayTypeService instance = new PayTypeService();
    private CommonService commonService = CommonService.getInstance();

    private PayTypeService() {
    }

    public static PayTypeService getInstance() {
        return instance;
    }

    /**
     * 获取默认的stripe支付方式
     *
     * @return
     */
    public PayType getStripePayType(Long shopId) {
        PayType payType = new PayType();
        payType.setShopId(shopId);
        payType.setName("Stripe");
        payType.setName_zh("Stripe");
        payType.setName_en("Stripe");
        payType.setType(ORDER_PAY_TYPE_STRIPE);
        payType.setImgId("");
        payType.setDefaultType(true);
        payType.setEnable(true);
        payType.setRuntimeVersion(Config.getInstance().getDolaVersion());
        payType.setImgId("us_stripe.png");
        return payType;
    }

    /**
     * 创建默认的支付类型
     *
     * @param shopId
     */
    public void createDefaultPayType(Long shopId) throws Exception {
        Shop shop = ShopService.getInstance().findShopById(shopId);

        //香港版本 8種
        if (Config.getInstance().isHkVersion()) {
            createDefaultPayType(shopId, shop, "現金", "Cash", ORDER_PAY_TYPE_CASH, "wallet.png", true);
            createDefaultPayType(shopId, shop, "微信", "WeChat Pay", ORDER_PAY_TYPE_WEIXIN, "wechat.png", true);
            createDefaultPayType(shopId, shop, "支付寶", "Alipay", ORDER_PAY_TYPE_ALIPAY, "alipay.png", true);
            createDefaultPayType(shopId, shop, "八達通", "Octopus", ORDER_PAY_TYPE_BA_DA_TONG, "octopus.png", true);
            createDefaultPayType(shopId, shop, "銀聯", "UnionPay", ORDER_PAY_TYPE_UNION_PAY, "unionPay.png", true);
            createDefaultPayType(shopId, shop, "Visa", "Visa", ORDER_PAY_TYPE_VISA, "visa.png", true);
            createDefaultPayType(shopId, shop, "Mastercard", "Mastercard", ORDER_PAY_TYPE_MASTER, "masterCard.png", true);
            createDefaultPayType(shopId, shop, "Amex", "Amex", ORDER_PAY_TYPE_AMERICAN_EXPRESS, "americaExpress.png", true);
        } else {
            //美國版本3種
            createDefaultPayType(shopId, shop, "現金", "Cash", ORDER_PAY_TYPE_CASH, "us_cash.png", true);
            createDefaultPayType(shopId, shop, "信用卡", "Credit Card", ORDER_PAY_TYPE_CREDIT_CARD, "us_creditCard.png", false);
            createDefaultPayType(shopId, shop, "支票", "Cheque", ORDER_PAY_TYPE_CHEQUE, "us_check.png", false);
            //默认不创建
            //createDefaultPayType(shopId, shop, "Stripe", "Stripe", ORDER_PAY_TYPE_STRIPE, "us_stripe.png", true);
        }
    }


    /**
     * 創建默認支付類型
     *
     * @param shopId
     * @param shop
     * @param name_zh
     * @param name_en
     * @param type
     * @throws Exception
     */
    public void createDefaultPayType(Long shopId, Shop shop, String name_zh, String name_en, int type, String imgId, boolean defaultType) throws Exception {
        PayType payType = new PayType();
        payType.setShopId(shopId);
        payType.setCompanyId(shop.getCompanyId());
        payType.setName(name_zh);
        payType.setName_zh(name_zh);
        payType.setName_en(name_en);
        payType.setDefaultType(defaultType);
        payType.setEnable(true);
        payType.setType(type);
        payType.setRuntimeVersion(Config.getInstance().getDolaVersion());
        payType.setImgId(imgId);
        commonService.directSave(payType);
    }

    /**
     * 获取默认的支付类型
     */
    public List<Integer> getDefaultType() {
        if (Config.getInstance().isHkVersion()) {
            return Arrays.asList(ORDER_PAY_TYPE_CASH, ORDER_PAY_TYPE_WEIXIN, ORDER_PAY_TYPE_ALIPAY,
                    ORDER_PAY_TYPE_BA_DA_TONG, ORDER_PAY_TYPE_UNION_PAY, ORDER_PAY_TYPE_VISA, ORDER_PAY_TYPE_MASTER, ORDER_PAY_TYPE_AMERICAN_EXPRESS);
        } else {
            return Arrays.asList(ORDER_PAY_TYPE_CASH, ORDER_PAY_TYPE_CREDIT_CARD, ORDER_PAY_TYPE_CHEQUE);
        }
    }

    /**
     * 查询支付方式
     *
     * @param shopId
     * @return
     */
    public List<PayType> findPayTypeList(Long shopId) {
        PayType payType = new PayType();
        payType.setShopId(shopId);
        payType.setRuntimeVersion(Config.getInstance().getDolaVersion());
        return commonService.searchAll(payType);
    }

    /**
     * 查询支付类型
     *
     * @param shopIdList
     * @return
     */
    public List<PayType> findPayTypeList(List<Long> shopIdList) {
        if (isEmpty(shopIdList)) {
            logger.info("pay type list is empty");
            return new ArrayList<>();
        }

        return shopIdList.stream().flatMap(shopId -> findPayTypeList(shopId).stream()).collect(Collectors.toList());
    }

    /**
     * 刷新缓存
     *
     * @param shopId
     */
    public void flushPayTypeListCash(Long shopId) throws IOException, ClassNotFoundException {
        String cacheKey = "pay.type.list." + shopId;
        JRedisUtil.delKV(cacheKey);
        findPayTypeListCache(shopId);
    }

    /**
     * 查询支付类型，先从缓存中读取
     * <p>
     * 去掉缓存查询，因为在开发环境很难去切换
     *
     * @param shopId
     * @return
     */
    public List<PayType> findPayTypeListCache(Long shopId) throws IOException, ClassNotFoundException {
        List<PayType> payTypeList = findPayTypeList(shopId);

        //过滤对应版本的数据
        return payTypeList.stream().filter(payType -> equals(payType.getRuntimeVersion(), Config.getInstance().getDolaVersion())).collect(Collectors.toList());
    }

    /**
     * 查询订单的支付方式，包括了stripe
     *
     * @param shopId
     * @return
     */
    public List<PayType> findPayTypeListCache_Stripe(Long shopId) throws Exception {
        List<PayType> payTypeList = findPayTypeListCache(shopId);

        //如果为空，初始化后，再重新添加
        if (isEmpty(payTypeList)) {
            createDefaultPayType(shopId);
            flushPayTypeListCash(shopId);
            payTypeList = findPayTypeListCache(shopId);
        }

        //如果没有包含stripe,再添加
        Optional<PayType> payTypeOptional = payTypeList.stream().filter(p -> p.getType().intValue() == ORDER_PAY_TYPE_STRIPE).findAny();
        if (!payTypeOptional.isPresent()) {
            payTypeList.add(getStripePayType(shopId));
        }

        return payTypeList;
    }

    /**
     * 按照支付类型，获取支付方式
     *
     * @param shopId
     * @param payTypeInt
     * @return
     */
    public PayType filterPayType(Long shopId, int payTypeInt) throws Exception {
        List<PayType> payTypeList = findPayTypeListCache_Stripe(shopId);
        return filterPayType(payTypeList, payTypeInt);
    }

    /**
     * 过滤支付类型
     *
     * @param payTypeList
     * @param payTypeInt
     * @return
     */
    public PayType filterPayType(List<PayType> payTypeList, int payTypeInt) throws ResponseStatusException {
        logger.info("will filter pay type is {}", payTypeInt);
        Optional<PayType> payTypeOptional = payTypeList.stream().filter(payType -> payTypeInt == payType.getType()).findAny();

        if (payTypeOptional.isPresent()) {
            return payTypeOptional.get();
        }

        VerifyUtil.throwError(ResponseStatus.SYSTEM_ERROR);
        return null;
    }

    /**
     * 过滤支付类型，按照支付类型的ID
     *
     * @param payTypeList
     * @param payTypeId
     * @return
     * @throws ResponseStatusException
     */
    public PayType filterPayType(List<PayType> payTypeList, long payTypeId) throws ResponseStatusException {
        logger.info("will filter pay type is {}", payTypeId);
        Optional<PayType> payTypeOptional = payTypeList.stream().filter(payType -> equals(payTypeId, payType.getId())).findAny();

        if (payTypeOptional.isPresent()) {
            return payTypeOptional.get();
        }

        VerifyUtil.throwError(ResponseStatus.SYSTEM_ERROR);
        return null;
    }

    /**
     * 过滤出订单的支付方式，并且添加中英文
     *
     * @param order
     * @return
     */
    public List<PayType> filterOrderPayTypeList(Order order) throws Exception {
        Integer payTypeBit = order.getPayTypeBit();
        List<Integer> payTypeIntList = bitNumberToIntList(payTypeBit);
        logger.info("pay type int list is {}", payTypeIntList);

        List<PayType> payTypeList = findPayTypeListCache_Stripe(order.getShopId());

        logger.info("pay type list is {}", payTypeList);

        List<PayType> filterPayTypeList = payTypeList.stream().filter(payType -> payTypeIntList.contains(getInt(payType.getType()))).collect(Collectors.toList());
        return filterPayTypeList;
    }

    /**
     * 获取支付方式的名称
     *
     * @param payType
     * @return
     */
    public PayTypeName payTypeToName(PayType payType) {
        PayTypeName payTypeName = new PayTypeName();
        payTypeName.setName_zh(payType.getName_zh());
        payTypeName.setName_en(payType.getName_en());

        return payTypeName;
    }

    /**
     * 过滤出订单的支付方式，并且添加中英文
     *
     * @param order
     * @return
     */
    public List<PayTypeName> filterOrderPayTypeNameList(Order order) throws Exception {
        logger.info("order {} pay type bit is {}", order.getId(), order.getPayTypeBit());
        List<PayType> payTypeList = filterOrderPayTypeList(order);
        logger.info("filter pay type list is {}", payTypeList);
        List<PayTypeName> payTypeNameList = payTypeList.stream().map(payType -> payTypeToName(payType)).collect(Collectors.toList());
        return payTypeNameList;
    }

    /**
     * 获取支付名称
     *
     * @param payType
     * @param zh
     * @return
     */
    public String getPayTypeName(PayType payType, boolean zh) {
        if (zh) {
            return payType.getName_zh();
        } else {
            return payType.getName_en();
        }
    }

    /**
     * 计算订单的支付类型，按照二进制
     *
     * @param order
     * @return
     */
    public int calOrderPayTypeBit(Order order) {
        List<Integer> payTypeList = new ArrayList<>();

        if (getBoolean(order.getWeixinPay())) {
            payTypeList.add(ORDER_PAY_TYPE_WEIXIN);
        }

        if (getBoolean(order.getAliPay())) {
            payTypeList.add(ORDER_PAY_TYPE_ALIPAY);
        }

        if (getBoolean(order.getCashPay())) {
            payTypeList.add(ORDER_PAY_TYPE_CASH);
        }

        if (getBoolean(order.getMasterCardPay())) {
            payTypeList.add(ORDER_PAY_TYPE_MASTER);
        }

        if (getBoolean(order.getVisaPay())) {
            payTypeList.add(ORDER_PAY_TYPE_VISA);
        }

        if (getBoolean(order.getBaDaTong())) {
            payTypeList.add(ORDER_PAY_TYPE_BA_DA_TONG);
        }

        if (getBoolean(order.getUnionPay())) {
            payTypeList.add(ORDER_PAY_TYPE_UNION_PAY);
        }

        if (getBoolean(order.getAmericanExpress())) {
            payTypeList.add(ORDER_PAY_TYPE_AMERICAN_EXPRESS);
        }

        if (getBoolean(order.getStripePay())) {
            payTypeList.add(ORDER_PAY_TYPE_STRIPE);
        }

        if (getBoolean(order.getCreditCard())) {
            payTypeList.add(ORDER_PAY_TYPE_CREDIT_CARD);
        }

        if (getBoolean(order.getCheque())) {
            payTypeList.add(ORDER_PAY_TYPE_CHEQUE);
        }

        return Long.valueOf(intListToBitNumber(payTypeList)).intValue();
    }

    /**
     * 给订单添加支付方式显示
     *
     * @param order
     */
    public void addPayTypeNameList(Order order) throws Exception {
        order.setPayTypeNameList(PayTypeService.getInstance().filterOrderPayTypeNameList(order));
        //添加支付方式的国际化
        order.setPayTypeName_zh(order.getPayTypeNameList().get(0).getName_zh());
        order.setPayTypeName_en(order.getPayTypeNameList().get(0).getName_en());
    }

    /**
     * 判断qf是否已经启用了
     *
     * @param shopId
     * @return
     */
    public boolean isQfConfig(Long shopId) throws Exception {
        logger.info("check shop {} qf config ", shopId);
        Shop shop = ShopService.getInstance().findShopById(shopId);
        if (isEmpty(shop.getQfSid())) {
            logger.info("qf sid not config");
            return false;
        }

        if (isEmpty(shop.getQfCode())) {
            logger.info("qf code not config");
            return false;
        }

        if (isEmpty(shop.getQfKey())) {
            logger.info("qf key not config");
            return false;
        }

        logger.info("qf config ok");
        return true;
    }

    /**
     * 查询最大类型的支付方式
     *
     * @param shopId
     * @return
     */
    public int maxPayType(Long shopId) {
        PayTypeDao payTypeDao = BeanUtil.getBean(PayTypeDao.class);
        return getInt(payTypeDao.maxPayType(shopId));
    }

    /**
     * 查询支付类型
     *
     * @return
     */
    public PayType findFoodPandaPayType(Long shopId) {
        PayType payType = new PayType();
        payType.setShopId(shopId);
        payType.setName_zh(Constant.FOOD_PANDA);
        payType.setDefaultType(true);
        return commonService.searchOne(payType);
    }

}
